/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.google.blockly.ohos.adapter;

import ohos.agp.components.BaseItemProvider;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;

import java.util.List;

public abstract class RecyclerAdapter<VH extends RecyclerAdapter.ViewHolder> extends BaseItemProvider {
    public static final int NO_POSITION = -1;
    public static final int INVALID_TYPE = -1;

    public abstract ViewHolder onCreateViewHolder(ComponentContainer parent, int viewType);

    public abstract int getItemCount();

    public abstract void onBindViewHolder(VH holder, int position) throws Exception;

    public abstract int getItemViewType(int position);

    private ViewHolder onCreateViewHolderDecor(ComponentContainer parent, int viewType) {
        ViewHolder holder = onCreateViewHolder(parent, viewType);
        holder.setType(viewType);
        return holder;
    }

    @Override
    public Component getComponent(int position, Component convertComponent, ComponentContainer parent) {
        ViewHolder itemViewHolder = null;
        try {
            int componentType = getItemViewType(position);
            if (convertComponent == null) {
                itemViewHolder = onCreateViewHolderDecor(parent, componentType);
            } else {
                itemViewHolder = (ViewHolder) convertComponent.getTag();
                if (itemViewHolder.getItemViewType() != componentType) {
                    itemViewHolder = onCreateViewHolderDecor(parent, componentType);
                }
            }
            bindViewHolder((VH) itemViewHolder, position);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return itemViewHolder.itemView;
    }

    public final void bindViewHolder(VH holder, int position) throws Exception {
        holder.mPosition = position;
        holder.itemView.setTag(holder);
        holder.setPosition(position);
        onBindViewHolder(holder, position, null);
    }

    public void onBindViewHolder(VH holder, int position, List<Object> payloads) throws Exception {
        onBindViewHolder(holder, position);
    }

    @Override
    public int getCount() {
        return getItemCount();
    }

    @Override
    public void notifyDataSetItemRemoved(int position) {
        super.notifyDataSetItemRemoved(position);
    }

    public void notifyItemChanged(int position) {
        notifyDataSetItemChanged(position);
    }

    @Override
    public void notifyDataSetItemChanged(int position) {
        super.notifyDataSetItemChanged(position);
    }

    @Override
    public void notifyDataSetItemRangeRemoved(int startPos, int countItems) {
        super.notifyDataSetItemRangeRemoved(startPos, countItems);
    }

    @Override
    public void notifyDataSetItemRangeChanged(int startPos, int countItems) {
        super.notifyDataSetItemRangeChanged(startPos, countItems);
    }

    @Override
    public void notifyDataSetItemRangeInserted(int startPos, int countItems) {
        super.notifyDataSetItemRangeInserted(startPos, countItems);
    }

    @Override
    public void notifyDataChanged() {
        super.notifyDataChanged();
    }

    @Override
    public void notifyDataSetItemInserted(int position) {
        super.notifyDataSetItemInserted(position);
    }

    public static class ViewHolder {
        public final Component itemView;
        private int itemViewType = INVALID_TYPE;
        public int mPosition = NO_POSITION;

        int mPreLayoutPosition = NO_POSITION;

        public void setType(int itemViewType) {
            this.itemViewType = itemViewType;
        }

        public final int getItemViewType() {
            return itemViewType;
        }

        protected void setPosition(int position) {
            this.mPosition = position;
        }

        public ViewHolder(Component itemComponent) {
            if (itemComponent == null) {
                throw new IllegalArgumentException("itemComponent may not be null");
            }
            this.itemView = itemComponent;
        }

        public Component getItemView() {
            return itemView;
        }

        public final int getHolderAdapterPosition() {
            return mPreLayoutPosition == NO_POSITION ? mPosition : mPreLayoutPosition;
        }
    }
}